package com.chuangjiangx.member.stored.ddd.domain.model;

import com.chuangjiangx.dddbase.Entity;
import com.chuangjiangx.domain.shared.model.PayEntry;
import com.chuangjiangx.domain.shared.model.PayTerminal;
import com.chuangjiangx.domain.shared.model.PayType;
import com.chuangjiangx.member.coupon.ddd.domain.model.MbrHasCouponId;
import com.chuangjiangx.member.basic.ddd.domain.model.MemberId;
import com.chuangjiangx.member.basic.ddd.domain.model.MerchantId;
import com.chuangjiangx.member.stored.ddd.domain.exception.MemberPaymentException;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;

/**
 * @author cj-ch
 * @date 2018/4/4 下午6:30
 */
@Getter
public class MbrOrder extends Entity<MbrOrderId> {
    /**
     * 会员订单编号
     */
    private String orderNumber;
    /**
     * 订单类型
     */
    private MbrOrderType type;
    /**
     * 商户
     */
    private MerchantId merchantId;
    /**
     * 商户用户
     */
    private Long merchantUserId;
    /**
     * 门店
     */
    private Long storeId;
    /**
     * 门店用户
     */
    private Long storeUserId;
    /**
     * 会员
     */
    private MemberId memberId;
    /**
     * 订单金额
     */
    private BigDecimal orderAmount;
    /**
     * 订单优惠金额
     */
    private BigDecimal discountAmount;
    /**
     * 实际支付金额
     */
    private BigDecimal paidAmount;
    /**
     * 退款金额
     */
    private BigDecimal refundAmount;
    /**
     * 支付时间
     */
    @Setter
    private Date paidTime;
    /**
     * 退款时间
     */
    private Date refundTime;
    /**
     * 会员领取的卡券/或充值赠送德卡券
     */
    private MbrHasCouponId mbrHasCouponId;
    /**
     * 订单状态
     */
    private MbrOrderStatus status;
    /**
     * 支付入口
     */
    @Setter
    private PayEntry payEntry;
    /**
     * 支付方式
     */
    @Setter
    private PayType payType;

    private String remark;
    /**
     * 支付终端
     */
    @Setter
    private PayTerminal payTerminal;
    /**
     * orderpay表的订单编号
     */
    @Setter
    private String orderPayNumber;
    /**
     * 充值规则Id
     */
    private MbrRechargeRuleId mbrRechargeRuleId;


    public MbrOrder(String orderNumber, MbrOrderType type, MerchantId merchantId,Long merchantUserId, Long storeId, Long storeUserId,
                    MemberId memberId,
                    BigDecimal orderAmount, BigDecimal discountAmount, BigDecimal paidAmount, BigDecimal refundAmount,
                    Date paidTime, Date refundTime, MbrHasCouponId mbrHasCouponId, MbrOrderStatus status,
                    PayEntry payEntry, PayType payType, String remark, PayTerminal payTerminal, String orderPayNumber,
                    MbrRechargeRuleId mbrRechargeRuleId) {
        this.orderNumber = orderNumber;
        this.type = type;
        this.merchantId = merchantId;
        this.merchantUserId = merchantUserId;
        this.storeId = storeId;
        this.storeUserId = storeUserId;
        this.memberId = memberId;
        this.orderAmount = orderAmount;
        this.discountAmount = discountAmount;
        this.paidAmount = paidAmount;
        this.refundAmount = refundAmount;
        this.paidTime = paidTime;
        this.refundTime = refundTime;
        this.mbrHasCouponId = mbrHasCouponId;
        this.status = status;
        this.payEntry = payEntry;
        this.payType = payType;
        this.remark = remark;
        this.payTerminal = payTerminal;
        this.orderPayNumber = orderPayNumber;
        this.mbrRechargeRuleId = mbrRechargeRuleId;
    }

    public void changeStatus(MbrOrderStatus status){
        this.status = status;
    }

    public void rechargeSuccess(Long merchantUserId,Long storeId,Long storeUserId,
                                PayEntry payEntry,PayType payType,PayTerminal payTerminal,
                                String orderPayNumber){
        if(!Objects.equals(this.type,MbrOrderType.RECHARGE)){
            throw new MemberPaymentException("","非会员充值订单");
        }
        if(!Objects.equals(this.status,MbrOrderStatus.NOT_PAID)){
            throw new MemberPaymentException("","错误会员充值订单充值成功前状态应该为:"+MbrOrderStatus.NOT_PAID);
        }
        this.status = MbrOrderStatus.PAID;
        this.merchantUserId = merchantUserId;
        this.storeId = storeId;
        this.storeUserId = storeUserId;
        this.paidTime = new Date();
        this.payEntry = payEntry;
        this.payType = payType;
        this.payTerminal = payTerminal;
        this.orderPayNumber = orderPayNumber;
    }

    public void rechargeSuccessGiftCoupon(MbrHasCouponId mbrHasCouponId){
        this.mbrHasCouponId = mbrHasCouponId;
    }

    /**
     * 卡券核销成功
     */
    public void couponUseSuccess(){
        this.status = MbrOrderStatus.PAID;
        this.paidTime = new Date();
    }


    /**
     * 订单退款
     * @param refund
     */
    public void refund(MbrOrderRefund refund){
        BigDecimal refundAmount = refund.getRefundAmount();
        if(refundAmount.compareTo(BigDecimal.ZERO) <= 0){
            throw new MemberPaymentException("", "退款金额不可小于等于0");
        }
        if(!MbrOrderStatus.canRefund(this.status)){
            throw new MemberPaymentException("", "订单当前状态不可以退款");
        }
        //计算可退金额
        BigDecimal canRefundAmout = this.paidAmount.subtract(this.refundAmount);
        if(refundAmount.compareTo(canRefundAmout) > 0){
            throw new MemberPaymentException("", "退款金额不能大于可退金额");
        }
        //累加退款金额
        this.refundAmount = this.refundAmount.add(refundAmount);
        this.refundTime = new Date();
        this.status = MbrOrderStatus.PARTIAL_REFUNDED;
        if(this.refundAmount.compareTo(this.paidAmount) == 0){
            //如果已经全额退款
            this.status = MbrOrderStatus.REFUNDED;
        }
        refund.setStatus(MbrOrderRefundStatus.SUCCESSFUL);
    }

    /**
     * 撤销订单
     */
    public void undo(Long merchantId, Long storeId, Long storeUserId, Integer userType){
        operateCheck(merchantId,storeId,storeUserId,userType);
        if(!Objects.equals(MbrOrderStatus.NOT_PAID,this.status)){
            throw new MemberPaymentException("", "当前订单状态不可撤销");
        }
        this.status = MbrOrderStatus.CANCELLED;
    }

    /**
     * 会员消费记录-编辑备注
     */
    public void editRemark(String remark){
        if(StringUtils.isEmpty(remark)){
            this.remark = StringUtils.EMPTY;
        }else{
            this.remark = remark;
        }
    }

    /**
     * 操作校验
     * @param merchantId
     * @param storeId
     * @param storeUserId
     * @param userType
     */
    public void operateCheck(Long merchantId, Long storeId, Long storeUserId, Integer userType){
        boolean r;
        switch (userType){
            case 0 :
                 r = Objects.equals(this.merchantId.getId(),merchantId);
                 break;
            case 1 :
                r = Objects.equals(this.merchantId.getId(),merchantId) && Objects.equals(this.storeId,storeId);
                break;
            case 2 :
                r = Objects.equals(this.merchantId.getId(),merchantId) && Objects.equals(this.storeUserId,storeUserId);
                break;
            default:
                throw new MemberPaymentException("","unknown userType");
        }
        if(!r){
            throw new MemberPaymentException("","您无权限对此订单进行操作");
        }
    }
}
